#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<sys/wait.h>
#include<string.h>
#include<sys/types.h>
#include<semaphore.h>

int main(int argc, char const *argv[]) {
    char share_name[100] = {0};
    char sem_name[100] = {0};
    sprintf(share_name, "test1");
    sprintf(sem_name, "semaphore");
    

    // 申请共享内存对象
    int fd = shm_open(share_name, O_RDWR | O_CREAT, 0644);
    int sem_fd = shm_open(sem_name, O_RDWR | O_CREAT, 0644);
    
    if (fd == -1) {
        perror("shm_open");
        exit(EXIT_FAILURE);
    }

    
    // 设置共享内存大小
    if (ftruncate(fd, 1024) == -1) {
        perror("ftruncate");
        close(fd);
        exit(EXIT_FAILURE);
    }

    if (ftruncate(sem_fd, sizeof(sem_t)) == -1) {
        perror("ftruncate");
        close(sem_fd);
        exit(EXIT_FAILURE);
    }

    // 映射共享内存
    int *addr = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (addr == MAP_FAILED) {
        perror("mmap");
        close(fd);
        exit(EXIT_FAILURE);
    }

    sem_t *sem_addr = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_SHARED, sem_fd, 0);
    if (sem_addr == MAP_FAILED) {
        perror("mmap");
        close(fd);
        exit(EXIT_FAILURE);
    }

    //初始化信号量
    sem_init(sem_addr, 1, 1);

    // 写入共享内存
    pid_t pid=fork();
    if (pid==0)
    {
        sem_wait(sem_addr);
        int temp=*addr;
        sleep(1);
        *addr=temp+1;
        sem_post(sem_addr);
    }else if (pid>0)
    {   
        sem_wait(sem_addr);
        int temp=*addr;
        sleep(1);
        *addr=temp+1;
        
        sem_post(sem_addr);     
    }else
    {
        perror("fork");
        exit(EXIT_FAILURE);
    }
    

    
    printf("The value of shared memory is: %d\n", *addr);

    // 关闭文件描述符
    close(fd);
    close(sem_fd);
    sem_destroy(sem_addr);

    // 解除映射共享内存


    // 关闭映射共享内存
    if (munmap(addr, 1024) == -1) {
        perror("munmap");
        exit(EXIT_FAILURE);
    }
    if (munmap(sem_addr, sizeof(sem_t)) == -1) {
        perror("munmap");
        exit(EXIT_FAILURE);
    }

    // 释放共享内存对象
    if (pid==0)
    {
        /* code */
        if (shm_unlink(share_name) == -1) {
        perror("shm_unlink");
        exit(EXIT_FAILURE);
    }
        if (shm_unlink(sem_name) == -1) {
            perror("shm_unlink");
            exit(EXIT_FAILURE);
        }
    }
    


    return 0;
}
